'''
Created on Mar 15, 2011

@author: mwarren1
'''

import re, time
import urllib2
import os.path
import email.header
import maildroplibs
from maildroplibs import Counter
import TaskBarIcon
from wx.tools.dbg import Logger

debug = Logger('downloader')
debug.SetStream(maildroplibs.DEBUGSTREAM)
debug(enable = maildroplibs.ENABLEDEBUG)

def stop():
    ImapDownloader.STOP = True
    
    debug("Instances Running: " + str(ImapDownloader.instanceList))
    for downloader in ImapDownloader.instanceList:
        downloader.__del__()

class ImapDownloader(object):
    '''
    classdocs
    '''

    STOP = False
    instanceList = []

    def __init__(self, settings, mlist = None):
        '''
        Constructor
        '''
        self.__class__.instanceList.append(self)
        
        self.settings = settings
        try:
            self.settings.verify()
        except maildroplibs.SettingsError as e:
            e.showError()
        
        ''' Build Message List '''
        if (mlist == None):
            self.messageList = []
        else:
            self.messageList = mlist
        

        ''' Set HTTP Proxy '''

        proxysetting = self.settings['PROXY']

        if (not self.__class__.STOP) and proxysetting == maildroplibs.PROXY_MAN and self.settings['HTTPPROXYENABLED']:
            proxy_url = str( self.settings['HTTPPROXYURL']) + ":" + str(self.settings['HTTPPROXYPORT'] )
            if not proxy_url.startswith('http://'):
                proxy_url = 'http://' + proxy_url
                
            debug("Using proxy \'" + proxy_url + "\' for link downloads")
            
            proxy_info = urllib2.ProxyHandler({self.settings['HTTPPROXYTYPE']: proxy_url })
            opener = urllib2.build_opener(proxy_info)
            
            if (not self.__class__.STOP) and (self.settings['HTTPPROXYUSERNAME'] is not None):
                passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
                passmgr.add_password(None, proxy_url, self.settings['HTTPPROXYUSERNAME'], self.settings.gethttpproxypassword())
                auth_info = urllib2.ProxyBasicAuthHandler(passmgr)
                opener = urllib2.build_opener(proxy_info, auth_info)
            
            urllib2.install_opener(opener)
        
        elif not self.__class__.STOP and proxysetting == maildroplibs.PROXY_AUTO:
            urllib2.install_opener(urllib2.build_opener(urllib2.HTTPHandler, urllib2.ProxyHandler()))
        elif not self.__class__.STOP and proxysetting == maildroplibs.PROXY_OFF:
            urllib2.install_opener(urllib2.build_opener(urllib2.HTTPHandler, urllib2.ProxyHandler({})))
            
    def __del__(self):
        if (not self.__class__.STOP):
            debug("Deleting ImapDownloader " + str(self))
        if (self.__class__.instanceList.count(self) > 0):
            self.__class__.instanceList.remove(self)
    
    def listMessagesAttachments(self):
        '''
        Prints list of messages and the attachment filenames
        '''
        if (not self.__class__.STOP):
            for message in self.messageList:
                if (not self.__class__.STOP):
                    for part in message.walk():
                        if (not self.__class__.STOP):
                            print part.get_content_type()
                            
                            #Print Email Info
                            if part.has_key('From'):
                                try:
                                    print "\tFrom:\t\t\t" + part.get('From')
                                except:
                                    pass #Skip unicode text
                            if part.has_key('To'):
                                try:
                                    print "\tTo:\t\t\t" + part.get('To')
                                except:
                                    pass #Skip unicode text
                            if part.has_key('Date'):
                                try:
                                    print "\tDate:\t\t\t" + part.get('Date')
                                except:
                                    pass #Skip unicode text
                            if part.has_key('Subject'):
                                try:
                                    print "\tSubject:\t\t" + part.get('Subject')
                                except:
                                    pass #Skip unicode text
                            
                            if part.has_key('Content-Disposition'):
                                print "\tFilename:\t\t" + part.get_filename()
                                filename = self.__decodeFilename(part.get_filename())
                                print "\tEncoded Filename:\t" + filename.encode('utf8')
                                print "\tFile Data:\t\t" + str(part.get_payload())[:50] + '...'
                            
                            print
        return True
    
    def downloadLinks(self, downloadfolder = None, overwrite = None):
        success = True
        dlList = []
        keepList = []
        
        if (not self.__class__.STOP):
            try:
                self.settings.verify()
            except maildroplibs.SettingsError as e:
                e.showError()
                return False, dlList
            
            if downloadfolder is None:
                downloadfolder = self.settings['DOWNLOADFOLDER']
            if overwrite is None:
                overwrite = self.settings['OVERWRITE']
                
            self.__checkDirExist(downloadfolder)
            
            for message in self.messageList:
                if (not self.__class__.STOP):
                    for part in message.walk():
                        #TODO: Add check for TXT message?
                        if (not self.__class__.STOP) and (part.get_content_type() == 'text/html'):
                            results = re.finditer(r'<\s*a\s*href\s*=\s*[\'"](http://dl.dropbox.com.*)[\'"]\s*>', part.as_string())
                            for result in results:
                                fileurl = result.groups()[0]
                                print "Link found in message: " + fileurl
                                debug("Link found in message: " + fileurl)
                                print
                                filename = fileurl[fileurl.rfind('/')+1:]
                                print filename
                                if (not self.__class__.STOP) and self.__inLimit():
                                    try:                           
                                        webfile = urllib2.urlopen(fileurl)
                                        fileinfo = webfile.info()
                                        filesize = -1
                                        if fileinfo['Content-length']:
                                            filesize = int(fileinfo['Content-length'])
                                                                    
                                        fullname = os.path.join(downloadfolder,filename)
                                        if not overwrite:
                                            fullname = self.__getUniqueName(fullname)
                                        print "Downloading File: " + os.path.basename(fullname) + " (" + str(filesize) + " bytes)"
                                        debug("Downloading File: " + os.path.basename(fullname) + " (" + str(filesize) + " bytes)")
                                        
                                        
                                        with open(fullname, 'wb') as file:
                                            file.write(webfile.read())
                                        webfile.close()
                                        dlList.append(fullname)
                                    except Exception as e:
                                        if (not self.__class__.STOP):
                                            print "Failed to Download Link: " + str(fileurl)
                                            print str(e)
                                            debug(str(e))
                                            print
                                            keepList.append(message) 
                                            # success = False
                                elif (not self.__class__.STOP):
                                    keepList.append(message) 
            
            if(not self.__class__.STOP):
                print "Keep List: " + str(keepList)
                            
            return success, dlList, keepList
                                
            
    def downloadAttachments(self, downloadfolder = None, overwrite = None):
        success = True
        dlList = []
        keepList = []
        
        if (not self.__class__.STOP):
            try:
                self.settings.verify()
            except maildroplibs.SettingsError as e:
                e.showError()
                return False, dlList
            
            if downloadfolder is None:
                downloadfolder = self.settings['DOWNLOADFOLDER']
            if overwrite is None:
                overwrite = self.settings['OVERWRITE']
            self.__checkDirExist(downloadfolder)
            
            try:
                for message in self.messageList:
                    if (not self.__class__.STOP):
                        debug("MessageList: " + str(self.messageList))
                        debug("Current Message: " + str([message]))
                        for part in message.walk():
                            if (not self.__class__.STOP) and part.has_key('Content-Disposition'):
                                if self.__inLimit():
                                    filename = self.__decodeFilename(part.get_filename())
                                    fullname = os.path.join(downloadfolder, filename)
                                    
                                    #Call Filename Function
                                    if not overwrite:
                                        fullname = self.__getUniqueName(fullname)
                                    try:
                                        print "Saving File: " + str(os.path.basename(fullname)).encode('utf8')
                                        debug("Saving File: " + str(os.path.basename(fullname)).encode('utf8'))
                                    except Exception:
                                        if (not self.__class__.STOP):
                                            print "Saving Unicode File"
                                            debug("Saving Unicode File")
                                    
                                    try:
                                        if (not self.__class__.STOP):    
                                            with open(fullname, 'wb') as file:
                                                file.write(part.get_payload(decode=True))
                                            dlList.append(fullname)
                                    except Exception as e:
                                        if (not self.__class__.STOP):
                                            debug.log(e.args)
                                            debug(str(e.args))
                                            debug.log("Could not download " + fullname)
                                            
                                else:
                                    keepList.append(message) 
            except Exception as e:
                if (not self.__class__.STOP):
                    print e.args
                    debug(str(e.args))
                    success = False
                    raise(e)
            
            if (not self.__class__.STOP):
                print "Keep List: " + str(keepList)
                            
            return success, dlList, keepList
                        
    def __decodeFilename(self, str):
        decoded = email.header.decode_header(str)
        fname = decoded[0][0]
        encoding = decoded[0][1]
        if (encoding != None):
            fname = fname.decode(encoding)
        return fname
     
    def __getUniqueName(self, fullname):
        while(os.path.exists(fullname)):
            filename = os.path.basename(fullname)
            filename, ext = os.path.splitext(filename)
            path = os.path.dirname(fullname)
            ''' need recursive savefile function '''
            filecount = re.search('(.*)\((\d+)\)',filename)
            if (filecount != None):
                filename = unicode(filecount.groups()[0])
                count = int(filecount.groups()[-1])
                count += 1
                filename = filename+"("+str(count)+")"+ext
                fullname = os.path.join(path,filename)
            else:
                filename = filename+"(1)"+ext
                fullname= os.path.join(path,filename)
        return fullname
    
    def __checkDirExist(self, dir):
        ''' Set Download Directory '''
        if (not self.__class__.STOP):
            downloaddir = os.path.abspath(dir)
        
        if (not self.__class__.STOP) and (not os.path.exists(downloaddir)):
            debug("Download Directory does not exist, creating: " + downloaddir)
            os.mkdir(downloaddir)
        
        if (not self.__class__.STOP):
            debug("Attachments will be saved to: " + str(downloaddir))
            print
        return downloaddir
    
    def __inLimit(self):
        if maildroplibs.TYPE:
            return maildroplibs.TYPE
        if time.strftime("%m%d%Y") == Counter.getItem('DATE'):
            Counter.setItem('COUNT', Counter.getItem('COUNT') + 1)
        else:
            Counter.setItem('DATE', time.strftime("%m%d%Y"))
            Counter.setItem('COUNT', 1)
        print "This is download #" + str(Counter.getItem('COUNT'))
        if Counter.getItem('COUNT') <= Counter.getItem('LIMIT'):
            return True
        else:
            print "Reached Daily Limit"
            TaskBarIcon.setToolTip("Reached Daily Limit", TaskBarIcon.NOCONN_ICON)
            return False
